/////////////////////////////////////////////////////////////////////////////
// Name:        ax_module.cpp
// Purpose:     AxModule: a self-contained unit of functionality
// Author:      Julian Smart
// Modified by:
// Created:     2009-03-25
// RCS-ID:      $Id$
// Copyright:   (c) Julian Smart
// Licence:     New BSD License
/////////////////////////////////////////////////////////////////////////////

#include "wx/wx.h"
#include "wx/hash.h"

#include "ax_resource/ax_module.h"

#include "wx/listimpl.cpp"

WX_DEFINE_LIST(AxModuleList);

IMPLEMENT_CLASS(AxModule, wxEvtHandler)

AxModuleList AxModule::m_modules;

AxModule::AxModule(): m_priority(axMEDIUM_PRIORITY)
{
    m_library = NULL;
}

void AxModule::RegisterModule(AxModule* module)
{
	// Put in priority order
    AxModuleList::Node *node;
    for ( node = m_modules.GetFirst(); node; node = node->GetNext() )
    {
		if (module->GetPriority() >= node->GetData()->GetPriority())
		{
			m_modules.Insert(node, module);
			return;
		}
	}

    m_modules.Append(module);
}

void AxModule::UnregisterModule(AxModule* module)
{
    m_modules.DeleteObject(module);
}

// Collect up all module-derived classes, create an instance of each,
// and register them.
void AxModule::RegisterModules()
{
#if wxCHECK_VERSION(2,9,0)

    for (wxClassInfo::const_iterator it  = wxClassInfo::begin_classinfo(),
                                     end = wxClassInfo::end_classinfo();
         it != end; ++it)
    {
        const wxClassInfo* classInfo = *it;

        if ( classInfo->IsKindOf(CLASSINFO(AxModule)) &&
             (classInfo != CLASSINFO(AxModule)) )
        {
            AxModule* module = (AxModule *)classInfo->CreateObject();
            wxASSERT_MSG( module != NULL, wxT("You forgot to use IMPLEMENT_DYNAMIC_CLASS."));
            if (module)
                RegisterModule(module);
        }
    }

#else

#if wxCHECK_VERSION(2,5,3) && !wxUSE_OLD_HASH_TABLE
    wxHashTable_Node *node;
#else
    wxNode *node;
#endif
    wxClassInfo* classInfo;

    wxClassInfo::sm_classTable->BeginFind();
    node = wxClassInfo::sm_classTable->Next();
    while (node)
    {
        classInfo = (wxClassInfo *)node->GetData();
        if ( classInfo->IsKindOf(CLASSINFO(AxModule)) &&
             (classInfo != CLASSINFO(AxModule)) )
        {
            AxModule* module = (AxModule *)classInfo->CreateObject();
            wxASSERT_MSG( module != NULL, wxT("You forgot to use IMPLEMENT_DYNAMIC_CLASS."));
            if (module)
                RegisterModule(module);
        }
        node = wxClassInfo::sm_classTable->Next();
    }
#endif
}

bool AxModule::InitializeModules(AxResourceLibrary* library)
{
    // Initialize user-defined modules
    AxModuleList::Node *node;
    for ( node = m_modules.GetFirst(); node; node = node->GetNext() )
    {
        if ( !node->GetData()->Init(library) )
        {
            // clean up already initialized modules - process in reverse order
            AxModuleList::Node *n;
            for ( n = node->GetPrevious(); n; n = n->GetPrevious() )
            {
                n->GetData()->OnExit();
            }

            return false;
        }
    }

    return true;
}

void AxModule::CleanUpModules()
{
    // Cleanup user-defined modules
    AxModuleList::Node *node;
    for ( node = m_modules.GetFirst(); node; node = node->GetNext() )
    {
        node->GetData()->Exit();
    }

    m_modules.DeleteContents(true);
    m_modules.Clear();
}

/// Finds the module with the given wxClassInfo
AxModule* AxModule::FindModule(wxClassInfo* info)
{
    AxModuleList::Node *node;
    for ( node = m_modules.GetFirst(); node; node = node->GetNext() )
    {
        if (node->GetData()->IsKindOf(info))
            return node->GetData();
    }
    return NULL;
}

